package com.example.limit.service;

import com.example.limit.entity.PurchaseRule;
import com.example.limit.entity.RuleGroup;
import com.example.limit.mapper.PurchaseRuleMapper;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Service
public class EnhancedPurchaseLimitService {
    
    private final PurchaseRuleMapper ruleMapper;
    private final RedisCounterService counterService;
    private final RedissonClient redissonClient;
    
    public EnhancedPurchaseLimitService(PurchaseRuleMapper ruleMapper, 
                                      RedisCounterService counterService, 
                                      RedissonClient redissonClient) {
        this.ruleMapper = ruleMapper;
        this.counterService = counterService;
        this.redissonClient = redissonClient;
    }
    
    /**
     * 增强的购买限制校验，支持规则组合
     */
    public PurchaseCheckResult checkPurchaseLimit(Long userId, String productId, 
                                                 String categoryId, int quantity, 
                                                 Map<String, Object> context) {
        String lockKey = counterService.generateKey("purchase:lock", userId.toString(), productId);
        RLock lock = redissonClient.getLock(lockKey);
        
        try {
            if (lock.tryLock(3, 10, TimeUnit.SECONDS)) {
                // 获取所有生效的规则并按优先级排序
                List<PurchaseRule> activeRules = getActiveRulesSorted();
                
                // 按规则组分组
                Map<Long, List<PurchaseRule>> groupedRules = activeRules.stream()
                    .collect(Collectors.groupingBy(rule -> rule.getGroupId() != null ? rule.getGroupId() : rule.getId()));
                
                // 校验每个规则组
                List<RuleCheckResult> results = new ArrayList<>();
                for (Map.Entry<Long, List<PurchaseRule>> entry : groupedRules.entrySet()) {
                    RuleCheckResult groupResult = checkRuleGroup(entry.getValue(), userId, productId, categoryId, quantity, context);
                    results.add(groupResult);
                    
                    // 如果组校验失败且优先级高，直接返回
                    if (!groupResult.isPassed() && isHighPriorityGroup(entry.getValue())) {
                        return new PurchaseCheckResult(false, "高优先级规则组校验失败", results);
                    }
                }
                
                boolean allPassed = results.stream().allMatch(RuleCheckResult::isPassed);
                return new PurchaseCheckResult(allPassed, allPassed ? "校验通过" : "部分规则校验失败", results);
            }
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            return new PurchaseCheckResult(false, "系统繁忙，请重试", Collections.emptyList());
        } finally {
            lock.unlock();
        }
        return new PurchaseCheckResult(false, "获取锁失败", Collections.emptyList());
    }
    
    /**
     * 校验规则组
     */
    private RuleCheckResult checkRuleGroup(List<PurchaseRule> rules, Long userId, String productId, 
                                         String categoryId, int quantity, Map<String, Object> context) {
        if (rules.isEmpty()) {
            return new RuleCheckResult(true, "无规则", Collections.emptyList());
        }
        
        // 单规则直接校验
        if (rules.size() == 1) {
            PurchaseRule rule = rules.get(0);
            boolean passed = checkSingleRule(rule, userId, productId, categoryId, quantity, context);
            return new RuleCheckResult(passed, passed ? "单规则校验通过" : "单规则校验失败", 
                Collections.singletonList(new RuleDetail(rule.getId(), rule.getRuleName(), passed)));
        }
        
        // 多规则组合校验
        Integer groupLogic = rules.get(0).getGroupLogic();
        List<RuleDetail> details = new ArrayList<>();
        boolean groupResult;
        
        if (groupLogic == null || groupLogic == 1) { // AND逻辑
            groupResult = true;
            for (PurchaseRule rule : rules) {
                boolean ruleResult = checkSingleRule(rule, userId, productId, categoryId, quantity, context);
                details.add(new RuleDetail(rule.getId(), rule.getRuleName(), ruleResult));
                groupResult = groupResult && ruleResult;
                if (!groupResult) break; // AND逻辑遇到false可提前结束
            }
        } else { // OR逻辑
            groupResult = false;
            for (PurchaseRule rule : rules) {
                boolean ruleResult = checkSingleRule(rule, userId, productId, categoryId, quantity, context);
                details.add(new RuleDetail(rule.getId(), rule.getRuleName(), ruleResult));
                groupResult = groupResult || ruleResult;
                if (groupResult) break; // OR逻辑遇到true可提前结束
            }
        }
        
        return new RuleCheckResult(groupResult, groupResult ? "规则组校验通过" : "规则组校验失败", details);
    }
    
    /**
     * 校验单个规则
     */
    private boolean checkSingleRule(PurchaseRule rule, Long userId, String productId, 
                                  String categoryId, int quantity, Map<String, Object> context) {
        // 先检查匹配条件
        if (!checkMatchCondition(rule, userId, productId, categoryId, context)) {
            return true; // 不匹配的规则视为通过
        }
        
        // 执行规则校验
        switch (rule.getRuleType()) {
            case 1: return checkUserDimensionRule(rule, userId, productId, categoryId, quantity);
            case 2: return checkProductDimensionRule(rule, userId, productId, categoryId, quantity);
            case 3: return checkTimeDimensionRule(rule, userId, productId, categoryId, quantity);
            case 4: return checkOrderDimensionRule(rule, userId, productId, categoryId, quantity);
            default: return true;
        }
    }
    
    /**
     * 检查匹配条件
     */
    private boolean checkMatchCondition(PurchaseRule rule, Long userId, String productId, 
                                      String categoryId, Map<String, Object> context) {
        // 简化实现：可以根据matchCondition字段实现复杂条件匹配
        // 这里先实现基础的目标值匹配
        if (rule.getTargetValue() != null && !rule.getTargetValue().isEmpty()) {
            switch (rule.getRuleType()) {
                case 1: // 用户维度
                    return rule.getTargetValue().equals(userId.toString());
                case 2: // 商品维度
                    if (rule.getSubType() == 3) { // 单品
                        return rule.getTargetValue().equals(productId);
                    } else if (rule.getSubType() == 4) { // 品类
                        return rule.getTargetValue().equals(categoryId);
                    }
                    break;
            }
        }
        return true; // 无目标值限制，匹配所有
    }
    
    // 原有的维度校验方法保持不变，这里省略重复代码...
    private boolean checkUserDimensionRule(PurchaseRule rule, Long userId, String productId, String categoryId, int quantity) {
        String key;
        java.time.Duration expireTime;
        
        switch (rule.getSubType()) {
            case 1: // 单用户限购
                key = counterService.generateKey("user:limit", userId.toString(), productId);
                expireTime = java.time.Duration.between(LocalDateTime.now(), rule.getEndTime());
                break;
            case 2: // 新老用户
                key = counterService.generateKey("user:type", userId.toString());
                expireTime = java.time.Duration.of(1, ChronoUnit.DAYS);
                break;
            default:
                return true;
        }
        
        return !counterService.isExceedLimit(key, rule.getLimitQuantity(), quantity, expireTime);
    }
    
    private boolean checkProductDimensionRule(PurchaseRule rule, Long userId, String productId, String categoryId, int quantity) {
        String key;
        java.time.Duration expireTime;
        
        switch (rule.getSubType()) {
            case 3: // 单品限购
                key = counterService.generateKey("product:limit", productId);
                expireTime = java.time.Duration.between(LocalDateTime.now(), rule.getEndTime());
                break;
            case 4: // 品类限购
                key = counterService.generateKey("category:limit", categoryId);
                expireTime = java.time.Duration.between(LocalDateTime.now(), rule.getEndTime());
                break;
            default:
                return true;
        }
        
        return !counterService.isExceedLimit(key, rule.getLimitQuantity(), quantity, expireTime);
    }
    
    private boolean checkTimeDimensionRule(PurchaseRule rule, Long userId, String productId, String categoryId, int quantity) {
        String key = counterService.generateKey("time:limit", userId.toString(), productId, 
                                              rule.getStartTime().toString(), rule.getEndTime().toString());
        java.time.Duration expireTime = java.time.Duration.between(LocalDateTime.now(), rule.getEndTime());
        
        return !counterService.isExceedLimit(key, rule.getLimitQuantity(), quantity, expireTime);
    }
    
    private boolean checkOrderDimensionRule(PurchaseRule rule, Long userId, String productId, String categoryId, int quantity) {
        if (rule.getSubType() == 6) { // 单订单限购
            return quantity <= rule.getLimitQuantity();
        } else if (rule.getSubType() == 7) { // 多订单累计
            String key = counterService.generateKey("order:accumulate", userId.toString(), productId);
            java.time.Duration expireTime = java.time.Duration.between(LocalDateTime.now(), rule.getEndTime());
            return !counterService.isExceedLimit(key, rule.getLimitQuantity(), quantity, expireTime);
        }
        return true;
    }
    
    @Cacheable(value = "activeRules", key = "'sorted'")
    public List<PurchaseRule> getActiveRulesSorted() {
        List<PurchaseRule> rules = ruleMapper.selectActiveRules();
        return rules.stream()
            .sorted(Comparator.comparing(PurchaseRule::getPriority))
            .collect(Collectors.toList());
    }
    
    private boolean isHighPriorityGroup(List<PurchaseRule> rules) {
        return rules.stream().anyMatch(rule -> rule.getPriority() != null && rule.getPriority() <= 5);
    }
    
    // 结果类
    public static class PurchaseCheckResult {
        private final boolean passed;
        private final String message;
        private final List<RuleCheckResult> groupResults;
        
        public PurchaseCheckResult(boolean passed, String message, List<RuleCheckResult> groupResults) {
            this.passed = passed;
            this.message = message;
            this.groupResults = groupResults;
        }
        
        // getters
        public boolean isPassed() { return passed; }
        public String getMessage() { return message; }
        public List<RuleCheckResult> getGroupResults() { return groupResults; }
    }
    
    public static class RuleCheckResult {
        private final boolean passed;
        private final String message;
        private final List<RuleDetail> ruleDetails;
        
        public RuleCheckResult(boolean passed, String message, List<RuleDetail> ruleDetails) {
            this.passed = passed;
            this.message = message;
            this.ruleDetails = ruleDetails;
        }
        
        // getters
        public boolean isPassed() { return passed; }
        public String getMessage() { return message; }
        public List<RuleDetail> getRuleDetails() { return ruleDetails; }
    }
    
    public static class RuleDetail {
        private final Long ruleId;
        private final String ruleName;
        private final boolean passed;
        
        public RuleDetail(Long ruleId, String ruleName, boolean passed) {
            this.ruleId = ruleId;
            this.ruleName = ruleName;
            this.passed = passed;
        }
        
        // getters
        public Long getRuleId() { return ruleId; }
        public String getRuleName() { return ruleName; }
        public boolean isPassed() { return passed; }
    }
}